package com.example.personal.aiagent.common.exception;

import com.example.personal.aiagent.common.constant.ErrorCode;
import com.example.personal.aiagent.common.model.vo.FailResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.validation.ConstraintViolationException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 全局异常处理
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理自定义服务异常
     *
     * @param ex 异常
     * @return 响应
     */
    @ExceptionHandler(CustomServiceException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public FailResponse handleCustomServiceException(CustomServiceException ex) {
        log.error("custom exception:", ex);
        if (CollectionUtils.isEmpty(ex.getParams())) {
            return new FailResponse(ex.getErrorCode());
        } else {
            return new FailResponse(ex.getErrorCode(), ex.getParams());
        }
    }

    /**
     * 处理校验异常 @RequestBody + 参数级别@Validated
     *
     * @param ex 异常
     * @return 响应
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public FailResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        List<String> errorMessages = ex.getBindingResult().getAllErrors().stream().map(
            DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.toList());
        return new FailResponse(ErrorCode.PARAM_ERROR_WITH_MESSAGE, Collections.singletonList(StringUtils.join(
            errorMessages, " , ")));
    }

    /**
     * 处理校验异常 @RequestParam + 类级别@Validated
     *
     * @param ex 异常
     * @return 响应
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public FailResponse handleConstraintViolationException(ConstraintViolationException ex) {
        return new FailResponse(ErrorCode.PARAM_ERROR_WITH_MESSAGE, Collections.singletonList(ex.getMessage()));
    }
}
